<script setup lang="ts">
import { onMounted, onUnmounted, ref, VNode, createVNode, render, computed, watch, h } from 'vue'
import { gpsbus, rtcbus } from '@/utils/gps/event'
import { createLayers2, createMap, setMap } from '@/utils/ol/maptools'
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElIcon } from 'element-plus'
import { Point } from 'ol/geom'
import { Style, Fill, Text, Icon } from 'ol/style'
import { Map, Feature } from 'ol'
import layerVector from 'ol/layer/Vector'
import Cluster from 'ol/source/Cluster'
import Overlay from 'ol/Overlay'
import sourceVector from 'ol/source/Vector'
import mapType from '@/utils/ol/maptype'
import mapPopup from '@/components/map-popup'
import { createPopup } from '@/utils/gps/createPopup'
import SendCmd from '@/views/dashboard/sendCmd.vue'
import DevWaring from '@/views/dashboard/devWarning.vue'
import { gdMap, browserLocal } from '@/utils/gps/amaputil'
import { computeIcon } from '@/utils/gps/iconTransform'
import poly from '@/assets/poly.png'
import { wsg2mapcoor } from '@/utils/gps/maptransform'
import { computeSubTitle } from '@/utils/gps/format'
import { router } from '@/router'
import { storeToRefs } from 'pinia'
import useDeviceStore from '@/store/gps/device'
import {Device} from "@/interface/home";
import MapControl from "@/components/map/mapControl.vue";
const deviceStore = useDeviceStore()
const { checkedDeviceList, checkedDeviceNodeIdList, checkedDeviceNodeId } = storeToRefs(deviceStore)

watch(
  () => checkedDeviceNodeId.value,
  (value) => {
    // setMapCenter(value)
  }
)

const mapRef = ref<HTMLDivElement>()
let map: Map
let baseLayers: any = null
let devicesLayer: layerVector<any>
let devicesSource: sourceVector
let feature: any

const popupRef = ref()

const currenDeviceInfo = computed(() => {
  return checkedDeviceList.value[checkedDeviceNodeId.value]
})

let curPopPos: any = null
const sendCmdRef = ref()
const devWarningRef = ref()

onMounted(() => {
  initMap()
  gpsbus.on('WS_CMD_POSITIONS', positionsCome)
  gpsbus.on('WS_CMD_EVENTS', eventsCome)
  gpsbus.on('RTC_INVITE', rtcCmd)
  gpsbus.on('RTC_CANCEL', rtcCmd)
  gpsbus.on('select', drawMarkers)
  gpsbus.on('selectAndPopup', setMapCenter)
  gpsbus.on('unSelect', removeEventFromDeviceList)
  gpsbus.on("repaint", repaintDevice)
})

onUnmounted(() => {
  gpsbus.off('WS_CMD_POSITIONS', positionsCome)
  gpsbus.off('WS_CMD_EVENTS', eventsCome)
  gpsbus.off('RTC_INVITE', rtcCmd)
  gpsbus.off('RTC_CANCEL', rtcCmd)
  gpsbus.off('select', drawMarkers)
  gpsbus.off('selectAndPopup', setMapCenter)
  gpsbus.off('unSelect', removeEventFromDeviceList)
  gpsbus.off("repaint", repaintDevice)
})

/**
 * 暴露数据和方法
 */
// defineExpose({
//   currenDeviceInfo
// })
/**
 * 初始化地图
 */
function initMap() {
  baseLayers = createLayers2()
  map = createMap(mapRef.value, baseLayers)
}

/**
 * 更换地图类型
 * @param val
 */
function mapTypeChange(val: string) {
  console.log(val)
  // closePopup()
  // // map.removeOverlay
  // map.removeLayer(devicesLayer)
  // baseLayers?.forEach((l) => map.removeLayer(l))
  // setMap(val)
  // baseLayers = createLayers2()
  // baseLayers?.forEach((l) => map.addLayer(l))
  // map.addLayer(devicesLayer)
}

/**
 * 创建图层及矢量图 用于绘制新的marker点
 */
function drawMarkers(devices: Device[]) {
  if (!devicesLayer) {
    devicesSource = new sourceVector()
    devicesLayer = new layerVector({
      source: new Cluster({
        distance: 100,
        source: devicesSource
      }),
      style: getStyle
    })
    map.addLayer(devicesLayer)
    setMapDeviceClickEvent()
  }
  devices.forEach((device) => {
    const { lng, lat } = wsg2mapcoor(device.longitude, device.latitude)
    const feature = new Feature({
      geometry: new Point([lng, lat])
    })
    feature.setId(device.nodeId)
    devicesSource?.addFeature(feature)
  })
}

/**
 * 获取矢量图样式
 * @param feature
 */
function getStyle(feature) {
  if (JSON.stringify(checkedDeviceList.value) === '{}') {
    return
  }
  const features = feature.get('features')
  const size = features.length
  if (size === 1) {
    const data = checkedDeviceList.value[features[0].getId()]!
    let iconPath: any = computeIcon(data)
    return new Style({
      image: new Icon({
        anchor: [40 / 2, 40 / 2],
        width: 40,
        height: 40,
        anchorOrigin: 'bottom-left',
        anchorXUnits: 'pixels',
        anchorYUnits: 'pixels',
        rotation: Math.PI / 180 * (data.direction % 360),
        src: iconPath
      }),
      text: new Text({
        text: `${data.plateNo} ${computeSubTitle(data)}`,
        offsetY: 30,
        scale: 1.5,
        textAlign: 'center',
        fill: new Fill({
          color: '#85ef74'
        }),
        backgroundFill: new Fill({
          color: '#679cff'
        }),
        // backgroundStroke: new Stroke({
        //   color: "#679cff",
        //   width: 2,
        // }),
        padding: [2, 10, 2, 10]
      })
    })
  } else {
    return new Style({
      image: new Icon({
        anchor: [0.5, 0.5],
        src: poly
      }),
      text: new Text({
        text: String(features.length),
        font: '14px sans-serif',
        fill: new Fill({
          color: '#fff'
        })
      })
    })
  }
}
/*
 * removeEventFromDeviceList: Map组件内部方法 用于删除marker点
 */
function removeEventFromDeviceList(nodeId: string[] | string) {
  // console.log('移除车', nodeId)
  if (Array.isArray(nodeId)) {
    for (let i = 0; i < nodeId.length; i++) {
      const feature = getFeature(nodeId[0])
      if (feature) {
        removeFeature(feature)
      }
    }
  } else {
    const feature = getFeature(nodeId)
    if (feature) {
      removeFeature(feature)
    }
    if (checkedDeviceNodeId.value === nodeId && curPopPos) {
      closePopup()
    }
  }
}

function repaintDevice({nodeId, icon}){
  const data = getFeature(nodeId)
  if(data) removeFeature(data)
  checkedDeviceList.value[nodeId].icon = icon
  drawMarkers([checkedDeviceList.value[nodeId]])
}

/**
 * 通过id获取指定的Feature
 * @param id
 */
function getFeature(id: string): Feature | null {
  return devicesSource?.getFeatureById(id)
}

/**
 * 移除指定的Feature
 * @param marker
 */
function removeFeature(marker: Feature) {
  devicesSource?.removeFeature(marker)
}

/**
 * 重绘小车位置
 * @param marker
 * @param nodeId
 */
function redrawPosition(nodeId, marker) {
  const { lng, lat } = wsg2mapcoor(marker.longitude, marker.latitude)
  marker.longitude = lng
  marker.latitude = lat
  getFeature(nodeId)?.setGeometry(new Point([marker.longitude, marker.latitude]))
}
/**
 * 绘制地图上的设备信息弹窗
 */
function drawMapDeviceInfoPopup(e) {
  feature = map.forEachFeatureAtPixel(e.pixel, (feature1) => feature1)
  if (feature) {
    const features = feature.get('features')
    const size = features.length
    if (size === 1) {
      checkedDeviceNodeId.value = features[0].getId()
      openPopup(features[0].getGeometry().getCoordinates())
    } else if (features.length > 1) {
      let nodeId = features[0].getId()
      const deviceData = checkedDeviceList.value[nodeId]
      const endPos = wsg2mapcoor(deviceData?.longitude, deviceData?.latitude)
      map.getView().animate({
        center: [endPos.lng, endPos.lat],
        zoom: 16,
        duration: 200
      })
    }
  } else {
    closePopup()
  }
}

/**
 * 创建弹窗
 * @param pos
 */
function openPopup(pos: number[]) {
  showPanel()
  const popup: VNode = createPopup(
    {
      header: () => h('div'),
      default: (close) =>
        h(mapPopup, {
          device: currenDeviceInfo.value,
          onClose: () => closePopup(),
          onCommand: () => sendCmdRef.value.init(checkedDeviceNodeId.value),
          onJumpPage: (name: string) => gpsbus.emit('switchMenu', name),
          onWarning: () => devWarningRef.value.init(checkedDeviceNodeId.value),
          onJumpWaybill: () =>
            router.push({
              path: '/dashboard/waybillMonitor',
              query: {
                sysOrgId: currenDeviceInfo.value.companyId,
                id: currenDeviceInfo.value.attribute.waybillId
              }
            })
        })
    },
    {
      target: popupRef.value,
      mask: false,
      rootElStyle: 'position: static; transform: none; margin: 0; width: 200px'
    }
  )
  let anchor = new Overlay({
    element: popup.el as any,
    positioning: 'bottom-center',
    stopEvent: true,
    offset: [-50, -30]
  })
  map.addOverlay(anchor)
  anchor.setPosition(pos)
  curPopPos = popup
  sAnchor = anchor
}

let sAnchor: any = null
function movePopup(pos: number[]) {
  if (sAnchor) {
    sAnchor.setPosition(pos)
  }
}

/**
 * 关闭弹出层
 */
function closePopup() {
  render(null, popupRef.value)
  popupRef.value.remove()
  curPopPos = null
  sAnchor = null
  console.log('closed')
}

/**
 * 地图-绑定设备点击事件
 */
function setMapDeviceClickEvent() {
  map.on('singleclick', drawMapDeviceInfoPopup)
}

/**
 * 设置地图中心点
 * @param nodeId
 */
function setMapCenter(nodeId: string) {
  const deviceData = checkedDeviceList.value[nodeId]
  const { lng, lat } = wsg2mapcoor(deviceData?.longitude, deviceData?.latitude)
  // console.log(lng, lat)
  if (!curPopPos) {
    openPopup([lng, lat])
  }
  movePopup([lng, lat])
  map.getView().animate({
    center: [lng, lat],
    // zoom: 16,
    duration: 500
  })
}

function showPanel() {
  if (currenDeviceInfo.value !== undefined) {
    const location = wsg2mapcoor(currenDeviceInfo.value.longitude, currenDeviceInfo.value.latitude)
    if (!currenDeviceInfo.value.address) {
      // 高德API逆编码
      gdMap(location)
        .then((result) => {
          currenDeviceInfo.value!.address = result
        })
        .catch(() => {
          currenDeviceInfo.value!.address = '无'
        })
    }
  }
}

/**
 * 车辆信息变更处理事件
 * @param id
 * @param info
 */
function refreshSocketPos(id: string, info) {
  const nodeId = "d-" + id
  if (checkedDeviceNodeId.value === nodeId && curPopPos) {
    const { lng, lat } = wsg2mapcoor(info.longitude, info.latitude)
    movePopup([lng, lat])
    map.getView().animate({
      center: [lng, lat],
      duration: 100
    })
  }
  if (devicesLayer && checkedDeviceNodeIdList.value.includes(nodeId)) {
    redrawPosition(nodeId, info)
  }
}
/**
 * 车辆信息变更通知
 * @param d
 */
const positionsCome = (d: any) => {
  refreshSocketPos(d.imei, d.position)
}

const eventsCome = (d: any) => {
  var imei = d.imei
  var event = d.event
  var pos = event.position
  if (pos) {
    // refreshSocketPos(imei, pos, true)
  }
}

const rtcCmd = (rtc: any) => {
  if ('invite' === rtc.type) {
    // this.rtcWsId = String(rtc.data.inviteId)
    // handleOperate('DeviceRtcVideo')
    setTimeout(() => {
      rtcbus.emit(rtc.type, rtc.data)
    }, 500)
  } else if ('cancel' === rtc.type) {
    // this.rtcWsId = null
    // this.handleOperateClose()
  }
}
</script>

<template>
  <div style="width: 100%; height: 100%; position: relative">
    <div ref="mapRef" class="map-home"></div>
    <div ref="popupRef"></div>
<!--  <div class="mapType">-->
<!--      <el-dropdown @command="mapTypeChange">-->
<!--        <span class="el-dropdown-link"> 切换地图 </span>-->
<!--        <template #dropdown>-->
<!--          <el-dropdown-menu>-->
<!--            <el-dropdown-item v-for="item in mapType" :key="item.id" :command="item.id">{{ item.name }}</el-dropdown-item>-->
<!--          </el-dropdown-menu>-->
<!--        </template>-->
<!--      </el-dropdown>-->
<!--    </div>-->

  <MapControl></MapControl>
    <SendCmd ref="sendCmdRef"></SendCmd>
    <DevWaring ref="devWarningRef"></DevWaring>
  </div>
</template>

<style scoped lang="css">
.map-home {
  width: 100%;
  height: 100%;
}
.mapType {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 99;
}

</style>
